using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using ZoneFiveSoftware.Common.Visuals;

namespace STCommon.View
{
    public class IconizedSTMenuItem : MenuItem
    {
        public IconizedSTMenuItem(ITheme visualTheme)
            : base(null)
        {
            OwnerDraw = true;

            InitTheme(visualTheme);
        }

        public IconizedSTMenuItem(ITheme visualTheme, string text)
            : base(text)
        {
            OwnerDraw = true;

            InitTheme(visualTheme);
        }

        public IconizedSTMenuItem(ITheme visualTheme, string text, EventHandler onClick)
            : base(text, onClick)
        {
            OwnerDraw = true;

            InitTheme(visualTheme);
        }

        public IconizedSTMenuItem(ITheme visualTheme, string text, MenuItem[] items)
            : base(text, items)
        {
            OwnerDraw = true;

            InitTheme(visualTheme);
        }

        public IconizedSTMenuItem(ITheme visualTheme, string text, EventHandler onClick, Shortcut shortcut)
            : base(text, onClick, shortcut)
        {
            OwnerDraw = true;

            InitTheme(visualTheme);
        }

        public IconizedSTMenuItem(ITheme visualTheme, MenuMerge mergeType, int mergeOrder, Shortcut shortcut, string text, EventHandler onClick, EventHandler onPopup, EventHandler onSelect, MenuItem[] items)
            : base(mergeType, mergeOrder, shortcut, text, onClick, onPopup, onSelect, items)
        {
            OwnerDraw = true;

            InitTheme(visualTheme);
        }

        public IconizedSTMenuItem(ITheme visualTheme, Image icon, Image checkedIcon)
            : this(visualTheme)
        {
            Icon = icon;
            CheckedIcon = checkedIcon;
        }

        public IconizedSTMenuItem(ITheme visualTheme, string text, Image icon, Image checkedIcon)
            : this(visualTheme, text)
        {
            Icon = icon;
            CheckedIcon = checkedIcon;
        }

        public IconizedSTMenuItem(ITheme visualTheme, string text, EventHandler onClick, Image icon, Image checkedIcon)
            : this(visualTheme, text, onClick)
        {
            Icon = icon;
            CheckedIcon = checkedIcon;
        }

        public IconizedSTMenuItem(ITheme visualTheme, string text, MenuItem[] items, Image icon, Image checkedIcon)
            : this(visualTheme, text, items)
        {
            Icon = icon;
            CheckedIcon = checkedIcon;
        }

        public IconizedSTMenuItem(ITheme visualTheme, string text, EventHandler onClick, Shortcut shortcut, Image icon, Image checkedIcon)
            : this(visualTheme, text, onClick, shortcut)
        {
            Icon = icon;
            CheckedIcon = checkedIcon;
        }

        public IconizedSTMenuItem(ITheme visualTheme, MenuMerge mergeType, int mergeOrder, Shortcut shortcut, string text, EventHandler onClick, EventHandler onPopup, EventHandler onSelect, MenuItem[] items, Image icon, Image checkedIcon)
            : this(visualTheme,mergeType, mergeOrder, shortcut, text, onClick, onPopup, onSelect, items)
        {
            Icon = icon;
            CheckedIcon = checkedIcon;
        }
        
        ~IconizedSTMenuItem()
        {
            m_BackgroundColor.Dispose();
            m_SeperatorColor.Dispose();
            m_HighlightColor.Dispose();
            m_BorderColor.Dispose();
            m_SelectedColor.Dispose();
            m_TextColor.Dispose();
        }
    
        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            LinearGradientBrush menuBarBrush = new LinearGradientBrush(new Rectangle(e.Bounds.X, e.Bounds.Y, 20, e.Bounds.Height + 1),
                                                                       m_VisualTheme.Control,
                                                                       m_VisualTheme.Window,
                                                                       LinearGradientMode.Horizontal);

            e.Graphics.FillRectangle(m_BackgroundColor, e.Bounds.X, e.Bounds.Y, e.Bounds.Width+1, e.Bounds.Height+1);
            e.Graphics.FillRectangle(menuBarBrush, e.Bounds.X, e.Bounds.Y, 20, e.Bounds.Height + 1);
            menuBarBrush.Dispose();

            if (base.Text == "-")
            {
                e.Graphics.FillRectangle(m_SeperatorColor, e.Bounds.X + 20,
                           e.Bounds.Y + 2, e.Bounds.Width - 20, e.Bounds.Height - 2);
            }
            else
            {
                // User-selected
                if (Selected)
                {
                    e.Graphics.FillRectangle(m_SelectedColor, e.Bounds.X + 1, e.Bounds.Y + 1,
                                             e.Bounds.Width - 1, e.Bounds.Height - 1);
                }
                // Highlighted (Mouse over)
                else if ((e.State & DrawItemState.Selected) != 0)
                {
                    e.Graphics.FillRectangle(m_HighlightColor, e.Bounds);
                    e.Graphics.DrawRectangle(m_BorderColor, e.Bounds.X, e.Bounds.Y,
                                             e.Bounds.Width - 1, e.Bounds.Height - 1);
                }

                if (Checked && CheckedIcon != null)
                {
                    Rectangle rIcon = new Rectangle(e.Bounds.X + 1, e.Bounds.Y + 3,
                                                    IconWidth,
                                                    IconHeight);

                    e.Graphics.DrawImageUnscaled(CheckedIcon, rIcon);
                }
                else if (!Checked && Icon != null)
                {
                    Rectangle rIcon = new Rectangle(e.Bounds.X + 1, e.Bounds.Y + 3,
                                                    IconWidth,
                                                    IconHeight);
                    e.Graphics.DrawImageUnscaled(Icon, rIcon);
                }

                if (!String.IsNullOrEmpty(base.Text))
                {
                    e.Graphics.DrawString(base.Text, SystemFonts.MenuFont, m_TextColor,
                                          e.Bounds.X + IconWidth + 6, // 6 = Border + "Prefix" blank
                                          e.Bounds.Y + 3);
                }
            }
        }

        protected override void OnMeasureItem(MeasureItemEventArgs e)
        {
            if (base.Text == "-")
            {
                e.ItemHeight = 4;
            }
            else
            {
                e.ItemHeight = 6 + IconHeight; // 6 = border
                e.ItemWidth = 2 + IconWidth; // 2 = border

                if (!String.IsNullOrEmpty(base.Text))
                {
                    // 22 = Text "prefix" & "postfix" blank
                    e.ItemWidth += 22 + Convert.ToInt32(e.Graphics.MeasureString(this.Text,
                                                                                 SystemFonts.MenuFont).Width);
                }
                else
                {
                    e.ItemWidth -= 14; // 14 pixels are automatically added, we don't want them.
                }
            }
        }

        private void InitTheme(ITheme visualTheme)
        {
            Debug.Assert(visualTheme != null);

            m_VisualTheme = visualTheme;

            m_BackgroundColor = new SolidBrush(m_VisualTheme.Window);
            m_SeperatorColor = new SolidBrush(m_VisualTheme.Control);
            m_HighlightColor = new SolidBrush(m_VisualTheme.Highlight);
            m_BorderColor = new Pen(m_VisualTheme.Control);
            m_SelectedColor = new SolidBrush(m_VisualTheme.Selected);
            m_TextColor = new SolidBrush(m_VisualTheme.ControlText);
        }

        private int IconWidth
        {
            get
            {
                if(m_Icon != null && m_CheckedIcon != null)
                {
                    return Math.Max(m_Icon.Width, m_CheckedIcon.Width);
                }
                else if (m_Icon != null)
                {
                    return m_Icon.Width;
                }
                else if (m_CheckedIcon != null)
                {
                    return m_CheckedIcon.Width;
                }

                return 0;
            }
        }

        private int IconHeight
        {
            get
            {
                if (m_Icon != null && m_CheckedIcon != null)
                {
                    return Math.Max(m_Icon.Height, m_CheckedIcon.Height);
                }
                else if (m_Icon != null)
                {
                    return m_Icon.Height;
                }
                else if (m_CheckedIcon != null)
                {
                    return m_CheckedIcon.Height;
                }

                return 0;
            }
        }

        public Image Icon
        {
            get { return m_Icon; }
            set
            {
                if (Icon != value)
                {
                    m_Icon = value;
                }
            }
        }

        public Image CheckedIcon
        {
            get { return m_CheckedIcon; }
            set
            {
                if (Icon != value)
                {
                    if (value == null)
                    {
                        m_CheckedIcon = Resources.Resources.CheckedMenuItem;
                    }
                    else
                    {
                        m_CheckedIcon = value;
                    }
                }
            }
        }

        public bool Selected
        {
            get { return m_Selected; }
            set
            {
                if (Selected != value)
                {
                    m_Selected = value;
                }
            }
        }

        private ITheme m_VisualTheme = null;
        private Image m_Icon = null;
        private Image m_CheckedIcon = Resources.Resources.CheckedMenuItem;
        private SolidBrush m_BackgroundColor = null;
        private SolidBrush m_SeperatorColor = null;
        private SolidBrush m_HighlightColor = null;
        private SolidBrush m_SelectedColor = null;
        private Pen m_BorderColor = null;
        private SolidBrush m_TextColor = null;
        private bool m_Selected = false;
    }
}
